package service

import (
	"encoding/json"
	"errors"
	"fmt"
	"n-server/internal/model"
	"n-server/internal/repository"
	"n-server/pkg/cache"

	"github.com/go-redis/redis/v8"
	"golang.org/x/crypto/bcrypt"
)

type UserService interface {
	RegisterUser(username, email, password string) (*model.User, error)            // 注册用户
	LoginUser(username, password string) (*model.User, error)                      // 登录用户
	DeleteUser(id uint) error                                                      // 删除用户
	UpdateUser(id uint, user *model.User) error                                    // 更新用户
	ListUsers(page, pageSize int, sort, order string) ([]model.User, int64, error) // 查询用户
}

type userServiceImpl struct {
	userRepository repository.UserRepository
	redis          *redis.Client
	cache          cache.Cache
}

func NewUserService(userRepository repository.UserRepository, redis *redis.Client, cache cache.Cache) UserService {
	return &userServiceImpl{
		userRepository: userRepository,
		redis:          redis,
		cache:          cache,
	}
}

// RegisterUser 注册用户
func (s *userServiceImpl) RegisterUser(username string, email string, password string) (*model.User, error) {
	// 根据邮箱判断用户是否已存在
	if _, err := s.userRepository.GetByEmail(email); err == nil {
		return nil, errors.New("用户已存在")
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return nil, errors.New("密码加密失败")
	}

	user := &model.User{
		Username: username,
		Email:    email,
		Password: string(hashedPassword),
		Role:     "user",
	}

	if err := s.userRepository.Greate(user); err != nil {
		return nil, errors.New("用户创建失败")
	}

	return user, nil
}

// LoginUser 登录用户
func (s *userServiceImpl) LoginUser(username string, password string) (*model.User, error) {
	// 1. 查询用户
	user, err := s.userRepository.GetByName(username)
	if err != nil {
		return nil, errors.New("用户不存在")
	}

	// 2. 校验密码
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
		return nil, errors.New("密码错误")
	}

	// 3. 登录成功，返回用户对象
	return user, nil
}

// DeleteUser 删除用户
func (s *userServiceImpl) DeleteUser(id uint) error {
	if err := s.userRepository.Delete(id); err != nil {
		return errors.New("删除用户失败")
	}
	return nil
}

// UpdateUser 更新用户
func (s *userServiceImpl) UpdateUser(id uint, user *model.User) error {
	old_user, err := s.userRepository.GetById(id)
	if err != nil {
		return errors.New("用户不存在")
	}

	// 设置用户ID
	user.ID = old_user.ID

	// 密码字段为空
	if user.Password == "" {
		user.Password = old_user.Password
	} else {
		// 不为空，新密码加密
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
		if err != nil {
			return errors.New("密码加密失败")
		}
		user.Password = string(hashedPassword)
	}

	// 更新用户信息
	if err := s.userRepository.Update(user); err != nil {
		return errors.New("更新用户失败")
	}
	return nil
}

// ListUsers 查询用户
func (s *userServiceImpl) ListUsers(page int, pageSize int, sort string, order string) ([]model.User, int64, error) {
	offset := (page - 1) * pageSize

	// 生成缓存键，包含排序参数
	cacheKey := fmt.Sprintf("users:list%d:%d:%s:%s", page, pageSize, sort, order)

	// 1. 从本地缓存获取
	if cacheData := s.cache.Get(cacheKey); cacheData != nil {
		if users, ok := cacheData.([]model.User); ok {
			return users, int64(len(users)), nil
		}
	}

	// 2. Redis 缓存
	if s.redis != nil {
		val, err := s.redis.Get(s.redis.Context(), cacheKey).Result()
		if err == nil && val != "" {
			var users []model.User
			if err := json.Unmarshal([]byte(val), &users); err == nil {
				return users, int64(len(users)), nil
			}
		}
	}

	// 3. 数据库查询
	users, total, err := s.userRepository.List(offset, pageSize, sort, order)
	if err != nil {
		return nil, 0, err
	}

	/*
		  // 写入 Redis
		  if s.redis != nil {
		  	  if data, err := json.Marshal(users); err == nil {
				  _ = s.redis.Set(s.redis.Context(), cacheKey, data, 5*time.Minute).Err()
			  }
		  }

		  // 写入本地缓存
		  s.cache.Set(cacheKey, users, 5*time.Minute)
	*/

	return users, total, nil
}
